Skip to content

Add code fix for MSTEST0031 — DoNotUseSystemDescriptionAttribute#7898

Merged
Evangelink merged 9 commits into
mainfrom
copilot/fix-mstest0031-description-attribute
May 11, 2026
Merged

Add code fix for MSTEST0031 — DoNotUseSystemDescriptionAttribute#7898
Evangelink merged 9 commits into
mainfrom
copilot/fix-mstest0031-description-attribute

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 28, 2026

MSTEST0031 warns when [System.ComponentModel.Description("...")] is applied to a test method, but provided no automated fix. This adds a code fixer that replaces the System.ComponentModel.DescriptionAttribute with MSTest's own DescriptionAttribute, using Roslyn's Simplifier to produce the correct name form based on the current using directives.

Fix behavior

  • Replaces [System.ComponentModel.Description("text")] (or [Description("text")] bound to System.ComponentModel) with MSTest's [Description("text")] (Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute)
  • Uses Simplifier.ReduceAsync with the fully-qualified Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute name so the output is always correct:
    • Simplified to [Description("text")] when the MSTest namespace is unambiguously in scope
    • Kept fully-qualified as [Microsoft.VisualStudio.TestTools.UnitTesting.Description("text")] when using System.ComponentModel is also present or when no namespace is imported

Before / After (typical case):

// Before
[TestMethod]
[System.ComponentModel.Description("My test description")]
public void MyTest() { }

// After
[TestMethod]
[Description("My test description")]
public void MyTest() { }

Before / After (short form with only using System.ComponentModel imported, no MSTest using):

// Before — [Description] resolves to System.ComponentModel.DescriptionAttribute
using System.ComponentModel;

[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]
[Description("My test description")]
public void MyTest() { }

// After
using System.ComponentModel;

[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]
[Microsoft.VisualStudio.TestTools.UnitTesting.Description("My test description")]
public void MyTest() { }

Note: Using [Description] in short form when both using System.ComponentModel and using Microsoft.VisualStudio.TestTools.UnitTesting are present results in a CS0104 ambiguity compile error — MSTEST0031 cannot fire in that scenario.

Changes

  • DoNotUseSystemDescriptionAttributeFixer.cs — new fixer using the semantic model to identify the System.ComponentModel.DescriptionAttribute, replaces its name with the fully-qualified MSTest DescriptionAttribute annotated with Simplifier.Annotation, then calls Simplifier.ReduceAsync to produce the minimal unambiguous form
  • CodeFixResources.resx — adds UseMSTestDescriptionAttributeInsteadFix title string
  • DoNotUseSystemDescriptionAttributeAnalyzerTests.cs — switches from EmptyCodeFixProvider to the new fixer; adds code-fix tests covering the standard case, the using System.ComponentModel (short-form and fully-qualified) case, and the fully-qualified (no using) case

Copilot AI requested review from Copilot and removed request for Copilot April 28, 2026 07:04
Copilot AI linked an issue Apr 28, 2026 that may be closed by this pull request
Copilot AI requested review from Copilot and removed request for Copilot April 28, 2026 07:25
Copilot AI changed the title [WIP] Add code fix for MSTEST0031 to replace Description attribute Add code fix for MSTEST0031 — DoNotUseSystemDescriptionAttribute Apr 28, 2026
Copilot AI requested a review from Evangelink April 28, 2026 07:25
@Evangelink
Copy link
Copy Markdown
Member

@copilot that seems wrong, we should instead use MSTest DescriptionAttribute

Copilot AI requested review from Copilot and removed request for Copilot April 28, 2026 07:44
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 28, 2026

@copilot that seems wrong, we should instead use MSTest DescriptionAttribute

Updated in aace8a7. The fixer now replaces [System.ComponentModel.Description("text")] with MSTest's own [Description("text")] (Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute) by simply renaming the attribute name to the simple identifier Description, which resolves to MSTest's attribute since the MSTest namespace is already in scope.

@Evangelink Evangelink marked this pull request as ready for review April 28, 2026 15:06
Copilot AI review requested due to automatic review settings April 28, 2026 15:06
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Workflow: Test Expert Reviewer 🧪
Date: 2026-04-28
Repository: microsoft/testfx

Key Findings

  1. [Coverage] Missing edge case: shortened attribute form with using System.ComponentModel;
    The added code-fix test covers only the fully-qualified [System.ComponentModel.Description("...")] syntax. The analyzer (which uses semantic analysis) would also trigger on the shortened [Description("...")] form when using System.ComponentModel; is in scope. In that scenario, the fixer's current implementation — unconditionally replacing the attribute name with the simple identifier Description — could produce ambiguous code that won't compile, because both System.ComponentModel.DescriptionAttribute and Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute would be in scope. A test case covering this form is needed to surface and protect against that behavior.

What's Good

  • The test follows the repo's established pattern (CSharpCodeFixVerifier<TAnalyzer, TFixer> alias, VerifyCodeFixAsync) perfectly.
  • Roslyn inline diagnostic markup ([|MyTestMethod|]) is used correctly.
  • The no-diagnostic path (WhenMethodWithoutTestMethodAttribute_HasSystemDescriptionAttribute_NoDiagnostic) is retained and correct.
  • No isolation or flakiness concerns — all tests run in-memory via the Roslyn testing framework.

Recommendations

  • Add a test case for the shortened [Description("text")] form when using System.ComponentModel; is present. This will reveal whether the fixer needs to also remove (or adjust) the conflicting using directive to produce valid code.

Generated by Test Expert Reviewer 🧪

🧪 Test quality reviewed by Test Expert Reviewer 🧪

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a C# code fix for MSTEST0031 (“DoNotUseSystemDescriptionAttribute”) so users can automatically replace System.ComponentModel.DescriptionAttribute on test methods with MSTest’s DescriptionAttribute, along with the necessary localized UI strings and a verifier update.

Changes:

  • Introduces DoNotUseSystemDescriptionAttributeFixer code fix provider.
  • Adds the new code fix title to CodeFixResources.resx and propagates it to localized *.xlf files.
  • Updates the analyzer unit test to validate the code fix result.
Show a summary per file
File Description
test/UnitTests/MSTest.Analyzers.UnitTests/DoNotUseSystemDescriptionAttributeAnalyzerTests.cs Switches to the real code fix provider and adds a code-fix verification.
src/Analyzers/MSTest.Analyzers.CodeFixes/DoNotUseSystemDescriptionAttributeFixer.cs New fixer that rewrites the attribute name for MSTEST0031.
src/Analyzers/MSTest.Analyzers.CodeFixes/CodeFixResources.resx Adds the code-fix title string.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.cs.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.de.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.es.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.fr.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.it.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ja.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ko.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.pl.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.pt-BR.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.ru.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.tr.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.zh-Hans.xlf Adds localized entry for the new code-fix title.
src/Analyzers/MSTest.Analyzers.CodeFixes/xlf/CodeFixResources.zh-Hant.xlf Adds localized entry for the new code-fix title.

Copilot's findings

  • Files reviewed: 16/16 changed files
  • Comments generated: 2

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Workflow: Expert Code Reviewer 🧠
Date: 2026-04-28
Repository: microsoft/testfx

Key Findings

[Correctness] Ambiguous/no-op fix when System.ComponentModel namespace is imported

File: src/Analyzers/MSTest.Analyzers.CodeFixes/DoNotUseSystemDescriptionAttributeFixer.cs (line 100)

The fix replaces the System attribute name with the bare identifier "Description". This works only in the narrow case where using Microsoft.VisualStudio.TestTools.UnitTesting; is in scope and using System.ComponentModel; is not.

Two broken scenarios the current test suite does not cover:

  • Both namespaces imported[Description] becomes ambiguous (CS0104), producing non-compiling code.
  • Only System.ComponentModel imported (with a fully-qualified [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]) → the replacement is syntactically identical to what was there before; the MSTest namespace still isn't in scope for Description, so the diagnostic would still fire.

Recommended fix: Use the fully-qualified MSTest name annotated with Simplifier.Annotation, letting the workspace simplifier reduce it only when the reference is unambiguous:

// using Microsoft.CodeAnalysis.Simplification;

AttributeSyntax newAttribute = systemDescriptionAttribute.WithName(
    SyntaxFactory.ParseName("Microsoft.VisualStudio.TestTools.UnitTesting.Description")
        .WithTriviaFrom(systemDescriptionAttribute.Name)
        .WithAdditionalAnnotations(Simplifier.Annotation));

SyntaxNode root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
Document updatedDocument = document.WithSyntaxRoot(root.ReplaceNode(systemDescriptionAttribute, newAttribute));
return await Simplifier.ReduceAsync(updatedDocument, cancellationToken: cancellationToken).ConfigureAwait(false);

A new test case should be added to cover the scenario where using System.ComponentModel; is also present, verifying that the result is unambiguous.

Positive Observations

  • The semantic-model–based attribute discovery (iterating attribute lists and comparing ContainingType via SymbolEqualityComparer) is correct and robust across fully-qualified and simple-name forms.
  • GetFixAllProvider()BatchFixer is the right choice for this single-replacement fix.
  • ConfigureAwait(false) is consistently applied on all awaited calls.
  • The .xlf localization files were auto-generated (not hand-edited), matching the repo convention.

Generated by Expert Code Reviewer

🧠 Reviewed by Expert Code Reviewer 🧠

@Evangelink
Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts in this pull request and address review comments

@Evangelink
Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts in this pull request

…1-description-attribute

# Conflicts:
#	src/Analyzers/MSTest.Analyzers.CodeFixes/CodeFixResources.resx

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 29, 2026

@copilot resolve the merge conflicts in this pull request

Resolved. Created a proper merge commit (18b3fdb) with two parents — the previous merge attempt was a single-parent commit. The branch is now fully up to date with main.

- Test 2: Use fully-qualified [System.ComponentModel.Description] in input
  to avoid CS0104 ambiguity when both namespaces are imported
- Tests 2 & 3: Expect 'Description' instead of 'DescriptionAttribute'
  since Roslyn Simplifier strips the Attribute suffix
Copilot AI review requested due to automatic review settings April 30, 2026 13:54
Copy link
Copy Markdown
Member

@Evangelink Evangelink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Workflow: Test Expert Reviewer 🧪
Date: 2026-04-30
Repository: microsoft/testfx

Key Findings

Good: Tests are well-isolated, use strong VerifyCodeFixAsync assertions that verify both the diagnostic location (via [|...|] markers) and the exact post-fix code. No shared mutable state, no timing dependencies, no flakiness patterns.

Coverage gap (1 finding): The PR description explicitly describes a scenario where the user writes the short form [Description("...")] with using System.ComponentModel in scope (where it resolves to System.ComponentModel.DescriptionAttribute). None of the three new code-fix tests cover this form — they all use the fully-qualified [System.ComponentModel.Description("...")] input. The inline comment above details the missing test case.

Recommendations

  1. Add a test for [Description("...")] (short form) + using System.ComponentModel in scope → fixer should produce [Microsoft.VisualStudio.TestTools.UnitTesting.Description("...")]. See inline comment for suggested test.

Generated by Test Expert Reviewer

🧪 Test quality reviewed by Test Expert Reviewer 🧪

Copy link
Copy Markdown
Member

@Evangelink Evangelink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Workflow: Expert Code Reviewer 🧠
Date: 2026-04-30
Repository: microsoft/testfx

Key Findings

No issues found. The implementation is correct and well-structured across all review dimensions.

Correctness

  • RegisterCodeFixesAsync correctly locates the MethodDeclarationSyntax by walking up from the diagnostic's token (placed on the method identifier by methodSymbol.CreateDiagnostic).
  • ReplaceWithMSTestDescriptionAttributeAsync uses the semantic model to identify the exact System.ComponentModel.DescriptionAttribute constructor symbol (via GetSymbolInfo + SymbolEqualityComparer.Default), which robustly handles aliases and qualified names.
  • The Simplifier.Annotation + Simplifier.ReduceAsync pattern correctly produces the minimal unambiguous form: simplified to [Description] when MSTest namespace is in scope without conflict, kept fully-qualified when using System.ComponentModel is also present or when no using is present. All three cases are tested.
  • The fully-qualified name Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute is correctly simplified by Roslyn (including Attribute suffix elision in attribute position) to match expected test outputs.

Threading / Concurrency
Design-time code-fixer code; no static mutable state; ConfigureAwait(false) used consistently throughout all async paths.

Performance
Not on a hot path; Roslyn caches the syntax tree so the double root retrieval (RegisterCodeFixesAsync + ReplaceWithMSTestDescriptionAttributeAsync) has no real cost.

Public API & Binary Compatibility
New public sealed class, pure addition. No existing API changes.

Cross-TFM
Analyzer targets C#+VB; fixer is C#-only (standard practice). No TFM-specific APIs used without guards.

Resources / IDisposable
No disposables introduced without cleanup.

Security
Operates purely on Roslyn syntax/semantic APIs; no injection or path traversal risk.

Defensive Coding
Null guards at all early-exit points; systemDescriptionAttributeSymbol is null and methodDeclaration is null checks both present.

Positive Observations

  • Follows all established code-fixer patterns in the codebase (same structure as UseAttributeOnTestMethodFixer, PreferDisposeOverTestCleanupFixer, etc.).
  • WellKnownTypeNames constants reused correctly — no magic strings in the fixer.
  • Three well-chosen test scenarios cover: typical case, ambiguity case (both usings), and no-using case.

Generated by Expert Code Reviewer

🧠 Reviewed by Expert Code Reviewer 🧠

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@Evangelink
Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts in this pull request

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 11, 2026

@copilot resolve the merge conflicts in this pull request

Resolved in e8f5608. The conflict in CodeFixResources.resx now includes both UseMSTestDescriptionAttributeInsteadFix (from this branch) and RemoveDuplicateTestMethodAttributeFix (from main), and the branch is fully up to date with main.

Copilot AI requested a review from Evangelink May 11, 2026 09:08
@Evangelink
Copy link
Copy Markdown
Member

@copilot test is failing with

test/UnitTests/MSTest.Analyzers.UnitTests/Verifiers/CSharpCodeFixVerifier`2.cs#L92

test/UnitTests/MSTest.Analyzers.UnitTests/Verifiers/CSharpCodeFixVerifier`2.cs(92,1): error : [WhenTestMethodHasShortFormDescriptionAttributeWithSystemComponentModelUsing_UsesFullyQualifiedMSTestDescription] [net8.0] Test method MSTest.Analyzers.Test.DoNotUseSystemDescriptionAttributeAnalyzerTests.WhenTestMethodHasShortFormDescriptionAttributeWithSystemComponentModelUsing_UsesFullyQualifiedMSTestDescription threw exception:
System.InvalidOperationException: Context: Diagnostics of test state
Expected diagnostic to start on line "9" was actually on line "8"

Expected diagnostic:
// /0/Test0.cs(9,17,9,29): warning MSTEST0031
VerifyCS.Diagnostic().WithSpan(9, 17, 9, 29),

Actual diagnostic:
// /0/Test0.cs(8,6): error CS0104: 'Description' is an ambiguous reference between 'System.ComponentModel.DescriptionAttribute' and 'Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute'
DiagnosticResult.CompilerError("CS0104").WithSpan(8, 6, 8, 17).WithArguments("Description", "System.ComponentModel.DescriptionAttribute", "Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute"),

…input

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot May 11, 2026 14:35
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 11, 2026

@copilot test is failing with

test/UnitTests/MSTest.Analyzers.UnitTests/Verifiers/CSharpCodeFixVerifier`2.cs#L92
...

Fixed in the latest commit. The root cause: having both using System.ComponentModel and using Microsoft.VisualStudio.TestTools.UnitTesting with the short form [Description] produces a CS0104 ambiguity compile error, so MSTEST0031 never fires in that scenario.

Updated the test to use using System.ComponentModel only (with fully-qualified [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]/[TestClass]), where [Description("...")] unambiguously resolves to System.ComponentModel.DescriptionAttribute. MSTEST0031 fires correctly, and the fixer produces the fully-qualified MSTest form.

@Evangelink Evangelink merged commit 8fde6e3 into main May 11, 2026
10 checks passed
@Evangelink Evangelink deleted the copilot/fix-mstest0031-description-attribute branch May 11, 2026 16:30
Evangelink added a commit that referenced this pull request May 12, 2026
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Co-authored-by: Amaury Levé <amauryleve@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add code fix for MSTEST0031 — DoNotUseSystemDescriptionAttribute

3 participants